package comment

import (
	"context"
	"fmt"
	"strings"

	"mall/common/modelx"
	"mall/common/resultx"
	"mall/common/utils/pointy"
	"mall/service/forum/model"
	"mall/service/forum/rpc/internal/svc"
	"mall/service/forum/rpc/types/forum"

	"github.com/sirupsen/logrus"
	"github.com/zeromicro/go-zero/core/logx"
)

type GetPostCommentListLogic struct {
	ctx    context.Context
	svcCtx *svc.ServiceContext
	logx.Logger
}

func NewGetPostCommentListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetPostCommentListLogic {
	return &GetPostCommentListLogic{
		ctx:    ctx,
		svcCtx: svcCtx,
		Logger: logx.WithContext(ctx),
	}
}

func (l *GetPostCommentListLogic) GetPostCommentList(in *forum.PostCommentListReq) (*forum.PostCommentListResp, error) {
	if in.Filter == nil || len(*in.Filter) == 0 {
		return nil, resultx.StatusError(resultx.REUQEST_PARAM_ERROR, "")
	}

	preloadMap, eagerLoadMap := modelx.ParsePreloadAndEagerLoad(in.Preload, in.EagerLoad)

	logrus.Info(fmt.Sprintf("GetPostCommentList preloadMap: %+v", preloadMap))

	logrus.Info(fmt.Sprintf("GetPostCommentList eagerLoadMap: %+v", eagerLoadMap))

	forumCommentEntityName := model.RpcEntityNames.ForumComment
	_, hasSettingMap := model.RpcEntityPreloadMap[forumCommentEntityName]
	if !hasSettingMap {
		return &forum.PostCommentListResp{}, nil
	}

	forumCommentRepositoryName := model.RepositoryNames.ForumComment
	columnMap, hasColumnMap := model.RepositoryPreloadMap[forumCommentRepositoryName]
	if !hasColumnMap {
		return &forum.PostCommentListResp{}, nil
	}

	var selectCols []string
	if preloadFields, hasPreloadFields := preloadMap[forumCommentEntityName]; hasPreloadFields {
		selectCols = modelx.ParseSelectColumns(preloadFields, columnMap)
	}

	filterMap := modelx.ParseFilter(in.Filter, columnMap)
	logrus.Info(fmt.Sprintf("GetPostCommentList filterMap: %+v", filterMap))
	if filterMap == nil {
		return nil, resultx.StatusError(resultx.REUQEST_PARAM_ERROR, "")
	}

	orderBy := modelx.ParseSorter(in.Sorter, columnMap)
	logrus.Info(fmt.Sprintf("GetPostCommentList orderBy: %s", orderBy))
	if len(orderBy) == 0 {
		orderBy = model.ForumCommentColumns.CommentDate + " DESC"
	}

	commentList, _, err := l.svcCtx.ForumComment.GetList(l.ctx, model.M{
		"offset": in.Page,
		"limit":  in.PageSize,
		// "search":  in.Search,
		"orderBy": orderBy,
		"select":  strings.Join(selectCols, ","),
	}, -1, filterMap)
	if err != nil {
		return nil, err
	}
	resp := &forum.PostCommentListResp{}
	if len(commentList) > 0 {
		var cids []any
		for _, v := range commentList {
			if v.CommentID > 0 {
				cids = append(cids, v.CommentID)
			}
		}

		idMetaMap := make(map[uint64][]*forum.MetaInfo)
		forumPostMetaEntityName := model.RpcEntityNames.ForumPostMeta
		if in.WithMeta != nil && *in.WithMeta > 0 {
			if subPreloadFields, hasSubPreloadFields := preloadMap[forumPostMetaEntityName]; hasSubPreloadFields {
				var metaKeys []any
				for _, field := range subPreloadFields {
					metaKeys = append(metaKeys, field)
				}
				if len(metaKeys) > 0 {
					metaFilterMap := make(map[string]map[string][]any)
					metaFilterMap[model.ForumCommentMetumColumns.CommentID] = map[string][]any{
						"in": cids,
					}
					metaFilterMap[model.ForumCommentMetumColumns.MetaKey] = map[string][]any{
						"in": metaKeys,
					}
					metaList, _, err := l.svcCtx.ForumComment.GetMeta(l.ctx, model.M{}, -1, metaFilterMap)
					if err != nil && err != model.ErrNotFound {
						return nil, err
					}

					if len(metaList) > 0 {
						for _, v := range metaList {
							idMetaMap[v.CommentID] = append(idMetaMap[v.CommentID], &forum.MetaInfo{
								Id:    pointy.GetPointer(v.MetaID),
								Key:   pointy.GetPointer(v.MetaKey),
								Value: pointy.GetPointer(v.MetaValue.String),
							})
						}
					}
				}
			}
		}
		for _, v := range commentList {
			var meta []*forum.MetaInfo
			if ms, ok := idMetaMap[v.PostID]; ok {
				meta = ms[:]
			}
			resp.List = append(resp.List, &forum.PostCommentInfo{
				Id:             pointy.GetPointer(v.PostID),
				ForumId:        pointy.GetPointer(v.ForumID),
				TopicId:        pointy.GetPointer(v.TopicID),
				PostId:         pointy.GetPointer(v.PostID),
				ParentId:       pointy.GetPointer(v.ParentID),
				UserId:         pointy.GetPointer(v.CommentUserID),
				NickName:       pointy.GetPointer(v.CommentUser),
				UserAvatar:     pointy.GetPointer(v.CommentUserURL),
				UserEmail:      pointy.GetPointer(v.CommentUserEmail),
				Ip:             pointy.GetPointer(v.CommentUserIP),
				AnonymousUser:  pointy.GetPointer(uint32(v.CommentUserAnonymous)),
				CommentContent: pointy.GetPointer(v.CommentContent),
				CommentType:    pointy.GetPointer(uint32(v.CommentType)),
				Status:         pointy.GetPointer(uint32(v.CommentStatus)),
				DelStatus:      pointy.GetPointer(uint32(v.DelStatus)),
				Sticky:         pointy.GetPointer(uint32(v.Sticky)),
				CreatedAt:      pointy.GetPointer(modelx.FormatTime(v.CommentDate, "")),
				Meta:           meta,
			})
		}
	}
	return resp, nil
}
